import _ from 'lodash'

// 触发规则 什么时候触发表单校验
const ruleTrigger = {
  INPUT: 'blur',
  INPUT_MAP: 'input',
  SELECT: 'change',
  RADIO: 'change',
  CHECKBOX: 'change',
  CASCADER: 'input',
  PROVINCE_CITY: 'input',
  DATE: 'change',
  MATRIX_SELECT: 'change',
  MATRIX_SCALE: 'change',
  MATRIX_INPUT: 'change'
}

/**
 * 验证身份证号码
 * @param { String } code 身份证号码
 */
function identityIDCard(code) {
  // 身份证号前两位代表区域
  const city = {
    11: '北京',
    12: '天津',
    13: '河北',
    14: '山西',
    15: '内蒙古',
    21: '辽宁',
    22: '吉林',
    23: '黑龙江 ',
    31: '上海',
    32: '江苏',
    33: '浙江',
    34: '安徽',
    35: '福建',
    36: '江西',
    37: '山东',
    41: '河南',
    42: '湖北 ',
    43: '湖南',
    44: '广东',
    45: '广西',
    46: '海南',
    50: '重庆',
    51: '四川',
    52: '贵州',
    53: '云南',
    54: '西藏 ',
    61: '陕西',
    62: '甘肃',
    63: '青海',
    64: '宁夏',
    65: '新疆',
    71: '台湾',
    81: '香港',
    82: '澳门',
    91: '国外 '
  }
  const idCardReg = /^[1-9]\d{5}(19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i // 身份证格式正则表达式
  let errorMessage = '' // 错误提示信息
  let isPass = true // 身份证验证是否通过（true通过、false未通过）

  // 如果身份证不满足格式正则表达式
  if (!code) {
    isPass = false
  } else if (!code.match(idCardReg)) {
    isPass = false
  } else if (!city[code.substr(0, 2)]) {
    // 区域数组中不包含需验证的身份证前两位
    isPass = false
  } else if (code.length === 18) {
    // 18位身份证需要验证最后一位校验位
    code = code.split('')
    // ∑(ai×Wi)(mod 11)
    // 加权因子
    const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
    // 校验位
    const parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]
    let sum = 0
    let ai = 0
    let wi = 0
    for (let i = 0; i < 17; i++) {
      ai = parseInt(code[i])
      wi = factor[i]
      sum += ai * wi // 开始计算并相加
    }
    const last = parity[sum % 11] // 求余
    if (last.toString() !== code[17]) {
      isPass = false
    }
  }
  return isPass

}

// 处理RADIO CHECKBOX 其他输入必填校验
const validateOtherInput = (rule, value, callback, formModel) => {
  // 0 等于选中其他
  if (value === 0 || (Array.isArray(value) && value.includes(0))) {
    if (!formModel[`${rule.field}other`]) {
      callback(new Error('请输入其他内容'))
    } else {
      callback()
    }
  } else {
    callback()
  }
}

// 校验矩阵输入
const validateMatrixInput = (rule, value, callback) => {
  // 0 等于选中其他
  let isValidate = true
  if (value) {
    // 如果是对象
    if (!_.isArray(value) && _.isObject(value)) {
      _.keys(value).forEach(key1 => {
        // 是不是对象
        let value1 = value[key1]
        // 矩阵填空
        if (!_.isArray(value1) && _.isObject(value1)) {
          _.keys(value1).forEach(key2 => {
            let value2 = value1[key2]
            if (!value2) {
              isValidate = false
              return
            }
          })
        }
      })
    }
    if (!isValidate) {
      callback(new Error('请输入全部矩阵组件的值'))
    } else {
      callback()
    }
  }
}
const validateMatrixSelect = (rule, value, callback, item) => {
  if (item.table.rows.length !== _.keys(value).length) {
    callback(new Error('请选择全部矩阵组件的值'))
  } else {
    callback()
  }
}

const validateMatrixScale = (rule, value, callback, item) => {
  if (item.table.rows.length > _.keys(value).length) {
    callback(new Error('请选择全部矩阵组件的值'))
  } else {
    item.table.rows.forEach(row => {
      if (!value[row.id]) {
        callback(new Error('请选择全部矩阵组件的值'))
        return
      }
    })
    callback()
  }
}

export default {
  data() {
    return {}
  },
  methods: {
    buildRule(cur, rules) {
      const config = cur.config
      // 其它输入框校验
      this.handleOtherInput(cur, config)
      if (Array.isArray(config.regList)) {
        this.handleInputValidate(cur, config)
        if (config.required) {
          // 矩阵系列组件 必填特殊处理 需要校验每项都有值
          this.handleSpecialRequired(cur, config)
          const required = {
            required: config.required,
            message: cur.placeholder
          }
          if (Array.isArray(config.defaultValue)) {
            required.type = 'array'
            required.message = `请至少选择一个${config.label}`
          }
          required.message === undefined && (required.message = `${config.label}不能为空`)
          config.regList.push(required)
        }
        rules[cur.vModel] = config.regList.map(item => {
          item.pattern && (item.pattern = eval(item.pattern))
          item.trigger = ruleTrigger && ruleTrigger[cur.typeId]
          return item
        })
      }
      if (config.children) this.buildRules(config.children, rules)
    },
    // 处理特殊组件非空校验
    handleSpecialRequired(cur, config) {
      // 矩阵系列组件 必填特殊处理 需要校验每项都有值
      let required = null
      if ('MATRIX_INPUT' === cur.typeId) {
        required = {
          validator: validateMatrixInput
        }
      } else if ('MATRIX_SELECT' === cur.typeId) {
        required = {
          validator: (rule, value, callback) => {
            validateMatrixSelect(rule, value, callback, cur)
          }
        }
      } else if ('MATRIX_SCALE' === cur.typeId) {
        required = {
          validator: (rule, value, callback) => {
            validateMatrixScale(rule, value, callback, cur)
          }
        }
      }
      if (required) {
        config.regList.push(required)
      }
    },
    // 多选 单选 其他输入框特殊处理校验规则
    handleOtherInput(cur, config) {
      // 必填其他输入框校验
      if (['RADIO', 'CHECKBOX'].includes(cur.typeId)) {
        const required = {
          validator: (rule, value, callback) => {
            validateOtherInput(rule, value, callback, this.formModel)
          },
          message: cur.placeholder
        }
        config.regList.push(required)
      }
    },
    // 输入框常用校验处理
    handleInputValidate(cur, config) {
      // INPUT数据类型校验
      if (['INPUT'].includes(cur.typeId) && cur.config.dataType) {
        const rule = cur.config.dataType
        if (rule.type === 'phone') {
          config.regList.push({
            type: null,
            pattern: /^1[3456789]\d{9}$/,
            message: rule.message
          })
        } else if (rule.type === 'identity') {
          config.regList.push({
            validator: (rule, value, callback) => {
              if (!identityIDCard(value)) {
                callback(new Error('请输入正确身份证'))
              }
              callback()
            },
            message: rule.message
          })
        } else {
          config.regList.push(rule)
        }
      }
    }
  }
}
